package ru.agiledev.aos.analyzer;

import ru.agiledev.aos.commons.dto.QType;
import ru.agiledev.aos.data.DictionaryLoader;
import ru.agiledev.aos.data.domain.IndicatorWord;
import ru.agiledev.aos.data.domain.WordTypes;

import java.util.*;

/**
 * Class contains HashSet fields for representing question types indicators
 * Created by a.kirillov
 */
class Dictionaries {

    //Aspect-oriented set of questions' types' indicators
    private HashSet<String> structureDescriptionFlags = new HashSet<String>();
    private HashSet<String> characteristicsDescriptionFlags = new HashSet<String>();
    private HashSet<String> workDescriptionFlags = new HashSet<String>();
    private HashSet<String> functionsDescriptionFlags = new HashSet<String>();
    private HashSet<String> missionDescriptionFlags = new HashSet<String>();
    private HashSet<String> usageDescriptionFlags = new HashSet<String>();
    private HashSet<String> correspondsToDescriptionFlags = new HashSet<String>();
    private HashSet<String> differencesDescriptionFlags = new HashSet<String>();
    private HashSet<String> commonsDescriptionFlags = new HashSet<String>();
    private HashSet<String> featuresDescriptionFlags = new HashSet<String>();
    private HashSet<String> possibilitiesDescriptionFlags = new HashSet<String>();


    //set of questions' types' indicators for question about goals
    private HashSet<String> goalsDescriptionFlags = new HashSet<String>();

    //set of questions' types' indicators for changes in sets
    private HashSet<String> setChangesDescriptionFlags = new HashSet<String>();

    //HashMap represents mapping of unique start word to possible types of questions(value) starting with this word(key)
    private HashMap<String, List<QType>> uniqueStartWords = new HashMap<String, List<QType>>();

    //HashMap for secondary indicator words (например "работа в условиях", "фунционирование при обстоятельсятвах")
    private HashSet<String> featuresDescriptionSecondaryFlags= new HashSet<String>();
    private HashSet<String> setChangesDescriptionSecondaryFlags= new HashSet<String>();

    //HashMap for domain words indication e.g. структура компании
    private HashSet<String> setChangesDomainWords= new HashSet<String>();

    //Empty chain producers for types
    private HashSet<String> structureDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> characteristicsDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> workDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> functionsDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> missionDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> usageDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> correspondsToDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> differencesDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> commonsDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> featuresDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> possibilitiesDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> goalsDescriptionEmptyChainProducers = new HashSet<String>();
    private HashSet<String> setChangesEmptyChainProducers = new HashSet<String>();

    //Additive empty chain producers and pointers
    private HashSet<String> usageDescriptionAdditiveEmptyChainProducers = new HashSet<String>();
    private HashSet<String> correspondsToDescriptionEmptyChainPointers = new HashSet<String>();
    private HashSet<String> featuresDescriptionAdditiveEmptyChainProducers = new HashSet<String>();
    private HashSet<String> goalsDescriptionEmptyChainPointers = new HashSet<String>();
    private HashSet<String> goalsDescriptionAdditiveEmptyChainProducers = new HashSet<String>();
    private HashSet<String> setChangesDescriptionAdditiveEmptyChainProducers = new HashSet<String>();


    //Conjuction pointers
    private HashSet<String> differencesDescriptionConjunctionPointers = new HashSet<String>();
    private HashSet<String> commonsDescriptionConjunctionPointers = new HashSet<String>();
    private HashSet<String> featuresDescriptionConjunctionPointers = new HashSet<String>();


    // Private constructor prevents instantiation from other classes
    private Dictionaries() {
        DictionaryLoader loader = new DictionaryLoader();
        List<IndicatorWord> indicatorList = loader.loadDictionaries();

        for (Iterator<IndicatorWord> iterator = indicatorList.iterator(); iterator.hasNext();) {
            IndicatorWord next = iterator.next();

            if(next.getWordType().equals(WordTypes.TYPE_WORD)){
                switch (next.getqType()){
                    case STRUCTURE_DESCRIPTION: structureDescriptionFlags.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionFlags.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionFlags.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionFlags.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionFlags.add(next.getValue()); break;
                    case USAGE_DESCRIPTION: usageDescriptionFlags.add(next.getValue()); break;
                    case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionFlags.add(next.getValue()); break;
                    case DIFFERENCES_DESCRIPTION: differencesDescriptionFlags.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionFlags.add(next.getValue()); break;
                    case FEATURES_DESCRIPTION: featuresDescriptionFlags.add(next.getValue()); break;
                    case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionFlags.add(next.getValue()); break;
                    case GOALS_DESCRIPTION: goalsDescriptionFlags.add(next.getValue()); break;
                    case SETS_CHANGES_DESCRIPTION: setChangesDescriptionFlags.add(next.getValue());
                }
            }else if(next.getWordType().equals(WordTypes.SECOND_TYPE_WORD)){
                switch (next.getqType()){
                  /*  case STRUCTURE_DESCRIPTION: structureDescriptionFlags.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionFlags.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionFlags.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionFlags.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionFlags.add(next.getValue()); break;
                    case USAGE_DESCRIPTION: usageDescriptionFlags.add(next.getValue()); break;
                    case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionFlags.add(next.getValue()); break;
                    case DIFFERENCES_DESCRIPTION: differencesDescriptionFlags.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionFlags.add(next.getValue()); break;                */
                    case FEATURES_DESCRIPTION: featuresDescriptionSecondaryFlags.add(next.getValue()); break;
                    /*case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionFlags.add(next.getValue()); break;
                    case GOALS_DESCRIPTION: goalsDescriptionFlags.add(next.getValue()); break;*/
                    case SETS_CHANGES_DESCRIPTION: setChangesDescriptionSecondaryFlags.add(next.getValue());
                }
            }else if(next.getWordType().equals(WordTypes.EMPTY_CHAIN_PRODUCER)){
                switch (next.getqType()){
                    case STRUCTURE_DESCRIPTION: structureDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case USAGE_DESCRIPTION: usageDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case DIFFERENCES_DESCRIPTION: differencesDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FEATURES_DESCRIPTION: featuresDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case GOALS_DESCRIPTION: goalsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case SETS_CHANGES_DESCRIPTION: setChangesEmptyChainProducers.add(next.getValue());
                }
            }else if(next.getWordType().equals(WordTypes.ADDITIVE_EMPTY_CHAIN_PRODUCER)){
                switch (next.getqType()){
                    /*case STRUCTURE_DESCRIPTION: structureDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionEmptyChainProducers.add(next.getValue()); break;*/
                    case USAGE_DESCRIPTION: usageDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;
                    /*case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case DIFFERENCES_DESCRIPTION: differencesDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionEmptyChainProducers.add(next.getValue()); break;   */
                    case FEATURES_DESCRIPTION: featuresDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;   /*
                    case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionEmptyChainProducers.add(next.getValue()); break;*/
                    case GOALS_DESCRIPTION: goalsDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;
                    case SETS_CHANGES_DESCRIPTION: setChangesDescriptionAdditiveEmptyChainProducers.add(next.getValue());
                }
            } else if(next.getWordType().equals(WordTypes.ADDITIVE_POINTER)){
                switch (next.getqType()){
                    /*case STRUCTURE_DESCRIPTION: structureDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case USAGE_DESCRIPTION: usageDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;*/
                    case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionEmptyChainPointers.add(next.getValue()); break;
                    /*case DIFFERENCES_DESCRIPTION: differencesDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FEATURES_DESCRIPTION: featuresDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;
                    case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionEmptyChainProducers.add(next.getValue()); break;*/
                    case GOALS_DESCRIPTION: goalsDescriptionEmptyChainPointers.add(next.getValue()); break;
//                    case SETS_CHANGES_DESCRIPTION: setChangesDescriptionFlags.add(next.getValue());
                }
            } else if(next.getWordType().equals(WordTypes.CONJUNCTION_POINTER)){
                switch (next.getqType()){
                    /*case STRUCTURE_DESCRIPTION: structureDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case CHARACTERISTICS_DESCRIPTION: characteristicsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case WORK_DESCRIPTION: workDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case FUNCTIONS_DESCRIPTION: functionsDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case MISSION_DESCRIPTION: missionDescriptionEmptyChainProducers.add(next.getValue()); break;
                    case USAGE_DESCRIPTION: usageDescriptionAdditiveEmptyChainProducers.add(next.getValue()); break;
                    case CORRESPONDS_TO_DESCRIPTION: correspondsToDescriptionEmptyChainPointers.add(next.getValue()); break;  */
                    case DIFFERENCES_DESCRIPTION: differencesDescriptionConjunctionPointers.add(next.getValue()); break;
                    case COMMONS_DESCRIPTION: commonsDescriptionConjunctionPointers.add(next.getValue()); break;
                    case FEATURES_DESCRIPTION: featuresDescriptionConjunctionPointers.add(next.getValue()); break;
                    /*case POSSIBILITIES_DESCRIPTION: possibilitiesDescriptionEmptyChainProducers.add(next.getValue()); break;*/
//                    case GOALS_DESCRIPTION: .add(next.getValue()); break;
//                    case SETS_CHANGES_DESCRIPTION: setChangesDescriptionFlags.add(next.getValue());
                }
            } else if(next.getWordType().equals(WordTypes.DOMAIN_WORD)){
                switch (next.getqType()){
                    case SETS_CHANGES_DESCRIPTION: setChangesDomainWords.add(next.getValue());
                }
            } else {

                if(uniqueStartWords.containsKey(next.getValue())){
                    uniqueStartWords.get(next.getValue()).add(next.getqType());
                } else {
                    List<QType> types = new ArrayList<QType>();
                    types.add(next.getqType());
                    uniqueStartWords.put(next.getValue(), types);
                }
            }

        }

    }

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance()
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class DictionariesHolder {
        public static final Dictionaries instance = new Dictionaries();
    }

    public static Dictionaries getInstance() {
        return DictionariesHolder.instance;
    }



    //getters
    public HashSet<String> getStructureDescriptionFlags() {
        return structureDescriptionFlags;
    }

    public HashSet<String> getCharacteristicsDescriptionFlags() {
        return characteristicsDescriptionFlags;
    }

    public HashSet<String> getWorkDescriptionFlags() {
        return workDescriptionFlags;
    }

    public HashSet<String> getFunctionsDescriptionFlags() {
        return functionsDescriptionFlags;
    }

    public HashSet<String> getMissionDescriptionFlags() {
        return missionDescriptionFlags;
    }

    public HashSet<String> getUsageDescriptionFlags() {
        return usageDescriptionFlags;
    }

    public HashSet<String> getCorrespondsToDescriptionFlags() {
        return correspondsToDescriptionFlags;
    }

    public HashSet<String> getDifferencesDescriptionFlags() {
        return differencesDescriptionFlags;
    }

    public HashSet<String> getCommonsDescriptionFlags() {
        return commonsDescriptionFlags;
    }

    public HashSet<String> getFeaturesDescriptionFlags() {
        return featuresDescriptionFlags;
    }

    public HashSet<String> getPossibilitiesDescriptionFlags() {
        return possibilitiesDescriptionFlags;
    }

    public HashSet<String> getGoalsDescriptionFlags() {
        return goalsDescriptionFlags;
    }

    public HashSet<String> getSetChangesDescriptionFlags() {
        return setChangesDescriptionFlags;
    }

    public HashSet<String> getDifferencesDescriptionConjunctionPointers() {
        return differencesDescriptionConjunctionPointers;
    }

    public HashMap<String, List<QType>> getUniqueStartWords() {
        return uniqueStartWords;
    }

    public HashSet<String> getFeaturesDescriptionSecondaryFlags() {
        return featuresDescriptionSecondaryFlags;
    }

    public HashSet<String> getStructureDescriptionEmptyChainProducers() {
        return structureDescriptionEmptyChainProducers;
    }

    public HashSet<String> getCharacteristicsDescriptionEmptyChainProducers() {
        return characteristicsDescriptionEmptyChainProducers;
    }

    public HashSet<String> getWorkDescriptionEmptyChainProducers() {
        return workDescriptionEmptyChainProducers;
    }

    public HashSet<String> getFunctionsDescriptionEmptyChainProducers() {
        return functionsDescriptionEmptyChainProducers;
    }

    public HashSet<String> getMissionDescriptionEmptyChainProducers() {
        return missionDescriptionEmptyChainProducers;
    }

    public HashSet<String> getUsageDescriptionEmptyChainProducers() {
        return usageDescriptionEmptyChainProducers;
    }

    public HashSet<String> getCorrespondsToDescriptionEmptyChainProducers() {
        return correspondsToDescriptionEmptyChainProducers;
    }

    public HashSet<String> getDifferencesDescriptionEmptyChainProducers() {
        return differencesDescriptionEmptyChainProducers;
    }

    public HashSet<String> getCommonsDescriptionEmptyChainProducers() {
        return commonsDescriptionEmptyChainProducers;
    }

    public HashSet<String> getFeaturesDescriptionEmptyChainProducers() {
        return featuresDescriptionEmptyChainProducers;
    }

    public HashSet<String> getPossibilitiesDescriptionEmptyChainProducers() {
        return possibilitiesDescriptionEmptyChainProducers;
    }

    public HashSet<String> getUsageDescriptionAdditiveEmptyChainProducers() {
        return usageDescriptionAdditiveEmptyChainProducers;
    }

    public HashSet<String> getCorrespondsToDescriptionEmptyChainPointers() {
        return correspondsToDescriptionEmptyChainPointers;
    }

    public HashSet<String> getCommonsDescriptionConjunctionPointers() {
        return commonsDescriptionConjunctionPointers;
    }

    public HashSet<String> getFeaturesDescriptionAdditiveEmptyChainProducers() {
        return featuresDescriptionAdditiveEmptyChainProducers;
    }

    public HashSet<String> getFeaturesDescriptionConjunctionPointers() {
        return featuresDescriptionConjunctionPointers;
    }

    public HashSet<String> getGoalsDescriptionEmptyChainProducers() {
        return goalsDescriptionEmptyChainProducers;
    }

    public HashSet<String> getGoalsDescriptionEmptyChainPointers() {
        return goalsDescriptionEmptyChainPointers;
    }

    public HashSet<String> getGoalsDescriptionAdditiveEmptyChainProducers() {
        return goalsDescriptionAdditiveEmptyChainProducers;
    }

    public HashSet<String> getSetChangesDescriptionSecondaryFlags() {
        return setChangesDescriptionSecondaryFlags;
    }

    public HashSet<String> getSetChangesDomainWords() {
        return setChangesDomainWords;
    }

    public HashSet<String> getSetChangesEmptyChainProducers() {
        return setChangesEmptyChainProducers;
    }

    public HashSet<String> getSetChangesDescriptionAdditiveEmptyChainProducers() {
        return setChangesDescriptionAdditiveEmptyChainProducers;
    }
}

